﻿package lz.controls
{ 
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.ui.Keyboard;
	
	import lz.controls.core.InvalidationType;
	import lz.controls.core.UIComponent;
	import lz.controls.events.ComponentEvent;
	import lz.controls.managers.IFocusManagerComponent;
 	/**
	 *LabelButton 类是一个抽象类，它通过添加标签、图标和切换功能扩展了 BaseButton 类。
	 *LabelButton 类是由 Button、CheckBox、RadioButton 和 CellRenderer 类创建的子类。
	 *LabelButton 组件作为 SimpleButton 类可与自定义外观状态结合使用，这些自定义外观状态支持 ScrollBar 按钮、NumericStepper 按钮、ColorPicker 样本等等。
	 */
	public class LabelButton extends BaseButton implements IFocusManagerComponent 
	{
		/**
		 * 组件的文本标签
		 */
		public var textField:TextField;
		/**
         * 标签相对于指定图标的位置。
		 */
		protected var _labelPlacement:String = ButtonLabelPlacement.RIGHT;		
		/**
         *指示按钮能否进行切换。
		 */
		protected var _toggle:Boolean = false;
		/**
         * 图标
		 */
		protected var icon:DisplayObject;
		/**
         * 旧的鼠标状态
		 */
		protected var oldMouseState:String;
		/**
         * 标签文本内容
		 */
		protected var _label:String = "Label";		
        /**
         *模式
         */
		protected var mode:String = "center"; // other option is "border".  Not currently used, but is reference in subclasses.
        /**
         * @private
         */
		private static var defaultStyles:Object = {
												  icon:null,
												  upIcon:null,downIcon:null,overIcon:null,disabledIcon:null,
												  selectedDisabledIcon:null,selectedUpIcon:null,selectedDownIcon:null,selectedOverIcon:null,
												  textFormat:null, disabledTextFormat:null,
												  textPadding:5, embedFonts:false
												  };
        /**
         * 检索当前组件的默认样式映射。
         */
		public static function getStyleDefinition():Object 
		{ 
			return mergeStyles(defaultStyles, BaseButton.getStyleDefinition());
		}

		/**
		 *  @private
		 *  Method for creating the Accessibility class.
         *  This method is called from UIComponent.
		 */
		public static var createAccessibilityImplementation:Function;
		/**
         *创建新的 LabelButton 组件实例。
		 */
		public function LabelButton() 
		{
			super();
		}
		/**
		 * 获取或设置组件的文本标签。 默认情况下，标签文本显示在按钮的中央。
		 * 注意：设置此属性将促使 labelChange 事件对象被调度。
		 * 默认值为 "Label"。
		 */        
		public function get label():String 
		{
			return _label;
		}		
		public function set label(value:String):void
		{
			_label = value;
			if (textField.text != _label)
			{
				textField.text = _label;
				dispatchEvent(new ComponentEvent(ComponentEvent.LABEL_CHANGE));
			}
			invalidate(InvalidationType.SIZE);
			invalidate(InvalidationType.STYLES);
		}	
		
		/**
		 * 标签相对于指定图标的位置。
		 * 在 ActionScript 中，可以使用以下常量来设置此属性：
		 * ButtonLabelPlacement.RIGHT
		 * ButtonLabelPlacement.LEFT
		 * ButtonLabelPlacement.BOTTOM
		 * ButtonLabelPlacement.TOP
		 * 默认值为 ButtonLabelPlacement.RIGHT。
		 */        
		public function get labelPlacement():String
		{
			return _labelPlacement;
		}		
		public function set labelPlacement(value:String):void 
		{
			_labelPlacement = value;
			invalidate(InvalidationType.SIZE);
		}	
		/**
         * 获取或设置一个布尔值，指示按钮能否进行切换。 true 值指示按钮可以进行切换；false 指示按钮不能进行切换。
		 * 如果该值为 true，则单击按钮将在选中状态和未选中状态之间进行切换。可以使用 selected 属性以编程方式获取或设置此状态。
		 * 如果该值为 false，则用户释放按钮后，它不再保持按下状态。在这种情况下，它的 selected 属性始终为 false。
		 * 注意：当 toggle 设置为 false 时，selected 将强制成为 false，因为只能选择切换按钮。
		 * 默认值为 false。
		 */		
		public function get toggle():Boolean 
		{
			return _toggle;
		}		
		public function set toggle(value:Boolean):void 
		{
			if (!value && super.selected) { selected = false; }
			_toggle = value;
			if (_toggle) { addEventListener(MouseEvent.CLICK,toggleSelected,false,0,true); }
			else { removeEventListener(MouseEvent.CLICK,toggleSelected); }
			invalidate(InvalidationType.STATE);
		}
		
		/**
         * @private (protected)
		 */
		protected function toggleSelected(event:MouseEvent):void
		{
			selected = !selected;
			dispatchEvent(new Event(Event.CHANGE, true));
		}	
		/**
		 * 获取或设置一个布尔值，指示切换按钮是否已切换至打开或关闭位置。 
		 * true 值指示按钮已切换至打开位置；false 值指示按钮已切换至关闭位置。
		 * 仅在以下情况才能设置此属性：toggle 属性设置为 true 时。
		 * 对于 CheckBox 组件，该值指示此框是否显示选中标记。
		 * 对于 RadioButton 组件，该值指示此组件是否处于选中状态。
		 * 用户可以通过单击组件来更改此属性，但是也可以通过编程方式来设置此属性。
		 * 如果 toggle 属性设置为 true，则更改此属性还会调度 change 事件。
		 * 默认值为 false。
		 */		
		override public function get selected():Boolean
		{
			return (_toggle) ? _selected : false;
		}			
		override public function set selected(value:Boolean):void 
		{
			_selected = value;
			if (_toggle)
			{
				invalidate(InvalidationType.STATE);
			}
		}
		/**
         * 配置UI
		 */
		override protected function configUI():void
		{
			super.configUI();
			
			textField = new TextField();
			textField.type = TextFieldType.DYNAMIC;
			textField.selectable = false;
			addChild(textField);
		}
		/**
         * 画界面
		 */		
		override protected function draw():void
		{
			if (textField.text != _label)
			{ 
				label = _label;
			}
			
			if (isInvalid(InvalidationType.STYLES,InvalidationType.STATE)) 
			{
				drawBackground();
				drawIcon();
				drawTextFormat();
				
				invalidate(InvalidationType.SIZE,false);
			}
			if (isInvalid(InvalidationType.SIZE))
			{
				drawLayout();
			}
			if (isInvalid(InvalidationType.SIZE,InvalidationType.STYLES))
			{
				if (isFocused && focusManager.showFocusIndicator) { drawFocus(true); }
			}
			validate(); // because we're not calling super.draw
		}
		/**
         * 画图标
		 */
		protected function drawIcon():void
		{			
			var oldIcon:DisplayObject = icon;
			
			var styleName:String = (enabled) ? mouseState : "disabled";
			if (selected)
			{ 
				styleName = "selected"+styleName.substr(0,1).toUpperCase()+styleName.substr(1);
			}
			styleName += "Icon";
			
			var iconStyle:Object = getStyleValue(styleName);
			if (iconStyle == null) 
			{
				// try the default icon:
				iconStyle = getStyleValue("icon");
			}			
			if (iconStyle != null)
			{ 
				icon = getDisplayObjectInstance(iconStyle);
			}
			if (icon != null) 
			{
				addChildAt(icon,1);
			}
			
			if (oldIcon != null && oldIcon != icon)
			{ 
				removeChild(oldIcon);
			}
		}
		/**
         * 绘制文本格式
		 */
		protected function drawTextFormat():void 
		{
			// Apply a default textformat
			var uiStyles:Object = UIComponent.getStyleDefinition();
			var defaultTF:TextFormat = enabled ? uiStyles.defaultTextFormat as TextFormat : uiStyles.defaultDisabledTextFormat as TextFormat;
			textField.setTextFormat(defaultTF);
			
			var tf:TextFormat = getStyleValue(enabled?"textFormat":"disabledTextFormat") as TextFormat;
			if (tf != null) 
			{
				textField.setTextFormat(tf);
			} else 
			{
				tf = defaultTF;
			}
			textField.defaultTextFormat = tf;
			setEmbedFont();
		}
		/**
         * 设置嵌入字体
		 */
		protected function setEmbedFont():void
		{
			var embed:Object = getStyleValue("embedFonts");
			if (embed != null) 
			{
				textField.embedFonts = embed;
			}	
		}
		/**
         * 绘制布局
		 */
		override protected function drawLayout():void
		{
			var txtPad:Number = Number(getStyleValue("textPadding"));
			var placement:String = (icon == null && mode == "center") ? ButtonLabelPlacement.TOP : _labelPlacement;
			textField.height =  textField.textHeight+4;
			
			var txtW:Number = textField.textWidth+4;
			var txtH:Number = textField.textHeight+4;
			
			var paddedIconW:Number = (icon == null) ? 0 : icon.width+txtPad;
			var paddedIconH:Number = (icon == null) ? 0 : icon.height+txtPad;
			textField.visible = (label.length > 0);
			
			if (icon != null) 
			{
				icon.x = Math.round((width-icon.width)/2);
				icon.y = Math.round((height-icon.height)/2);
			}
			
			var tmpWidth:Number;
			var tmpHeight:Number;
			
			if (textField.visible == false)
			{
				textField.width = 0;
				textField.height = 0;
			} else if (placement == ButtonLabelPlacement.BOTTOM || placement == ButtonLabelPlacement.TOP) {
				tmpWidth = Math.max(0,Math.min(txtW,width-2*txtPad));
				if (height-2 > txtH)
				{
					tmpHeight = txtH;
				} else 
				{
					tmpHeight = height-2;
				}
				
				textField.width = txtW = tmpWidth;
				textField.height = txtH = tmpHeight;
				
				textField.x = Math.round((width-txtW)/2);
				textField.y = Math.round((height-textField.height-paddedIconH)/2+((placement == ButtonLabelPlacement.BOTTOM) ? paddedIconH : 0));
				if (icon != null) 
				{
					icon.y = Math.round((placement == ButtonLabelPlacement.BOTTOM) ? textField.y-paddedIconH : textField.y+textField.height+txtPad);
				}
			} else
			{
				tmpWidth =  Math.max(0,Math.min(txtW,width-paddedIconW-2*txtPad));	
				textField.width = txtW = tmpWidth;	
				
				textField.x = Math.round((width-txtW-paddedIconW)/2+((placement != ButtonLabelPlacement.LEFT) ? paddedIconW : 0));
				textField.y = Math.round((height-textField.height)/2);
				if (icon != null) 
				{
					icon.x = Math.round((placement != ButtonLabelPlacement.LEFT) ? textField.x-paddedIconW : textField.x+txtW+txtPad);
				}
			}
			super.drawLayout();			
		}
		/**
         * 键盘按下事件
		 */		
		override protected function keyDownHandler(event:KeyboardEvent):void 
		{
			if (!enabled) { return; }
			if (event.keyCode == Keyboard.SPACE) 
			{
				if(oldMouseState == null) 
				{
					oldMouseState = mouseState;
				}
				setMouseState("down");
				startPress();
			}
		}
		/**
         * 键盘松开事件
		 */		
		override protected function keyUpHandler(event:KeyboardEvent):void
		{
			if (!enabled) { return; }
			if (event.keyCode == Keyboard.SPACE) 
			{
				setMouseState(oldMouseState);
				oldMouseState = null;
				endPress();
				dispatchEvent(new MouseEvent(MouseEvent.CLICK));
			}
		}
		/**
         * 设备可访问性
		 */
		override protected function initializeAccessibility():void 
		{
			if (LabelButton.createAccessibilityImplementation != null)
				LabelButton.createAccessibilityImplementation(this);
		}
	}
}